#ifndef AUBO_SCOPE_RENDER_FORM2_H
#define AUBO_SCOPE_RENDER_FORM2_H

#include <QMap>
#include <QCache>

#include <qrender/render_view.h>

class QGridLayout;

class Q3dsRenderer;
class LineRenderer;
class AxisRenderer;
class SphereRenderer;
class PointCloudRenderer;
class BoxRenderer;
class Camera;

namespace Ui {
class RenderForm;
}

class RenderForm : public RenderView
{
    Q_OBJECT

    /// 路点轨迹
    struct WaypointTrack
    {
        WaypointTrack();
        void setPose(const std::vector<double> &pose);
        void updateTrajs();

        std::vector<double> pose{}; ///< 当前路点的位姿(包含TCP偏移)
        std::shared_ptr<SphereRenderer> r_waypoints_{ nullptr };

        std::vector<std::vector<double>>
            move_traj{}; ///< 从前一个路点到当前路点的轨迹点
        std::vector<std::vector<double>> blend_traj{}; ///< 路点处的交融轨迹点
        std::shared_ptr<LineRenderer> r_traj_{ nullptr };
    };

    /// 点云
    struct PointCloud
    {
        PointCloud();
        void setPoints(const std::vector<std::vector<double>> points,
                       const QColor &color);

        std::vector<std::vector<double>> points;
        QColor color;

        std::shared_ptr<PointCloudRenderer> r_point_cloud;
    };

public:
    enum ShowOptions : uint8_t
    {
        None = 0,
        Ground = 0x01,
        TargetRobot = 0x02,
        RealRobot = 0x04,
        Coordinate = 0x08,
        Track = 0x10,
        Point = 0x20,
        View = 0x40,
        All = 0xFF,
    };

public:
    RenderForm(QWidget *parent = nullptr);
    ~RenderForm();

    // ----- 数据操作 -----
    /// 重新加载机器人模型
    ///
    /// RenderForm 构造时默认加载i5的模型，
    /// 这里是在知道真正机器人模型之后，重新进行加载
    bool reload(const QString &robot_type,
                const std::unordered_map<std::string, std::vector<double>> &dh);

    /// 获取视图偏转角（视图坐标系：X轴朝上，Y轴朝右，Z轴朝里）
    double getViewRotationAngleX();
    double getViewRotationAngleY();
    double getViewRotationAngleZ();

    /// 设置视图偏转角
    void setViewRotationAngleX(double angle);
    void setViewRotationAngleY(double angle);
    void setViewRotationAngleZ(double angle);

    /**
     * @brief setRobotGravity 设置机器人重力矩阵
     * @param pose_gravity 重力在三个方向的分量 {gx, gy, gz}
     */
    void setRobotGravity(std::vector<double> gravity_component);

    /// 设置真实机器人关节角度
    void setRealJointPositions(const std::vector<double> &position);

    /// 目标机械臂绘制
    void setTargetJointPositions(const std::vector<double> &position);

    /// 设置末端位置
    void setTcpPose(const std::vector<double> &pose);

    /// 根据关节和位姿获取机器人模型截图
    QPixmap *grabFromJoints(const std::vector<double> &joints,
                            const std::vector<double> &pose);

    /// 初始视角
    void initView();

    /// 锁定视角
    void fixDisplay();

    /// 解锁视角
    void freeDisplay();

    // 轨迹
    void setMoveTrack(void *wp,
                      const std::vector<std::vector<double>> &trackList);
    void setBlendTrack(void *wp,
                       const std::vector<std::vector<double>> &trackList);

    // 路点
    bool hasWaypoint(void *wp);
    bool addWaypoint(void *wp, const std::vector<double> &pose);
    void deleteWaypoint(void *wp);
    void clearWaypoints();

    // 坐标轴
    void setCoordinatesVisiable(bool visiable);
    void setCoordinate(const QString &name, const std::vector<double> &pose);
    std::vector<double> getCoordinate(const QString &name,
                                      const std::vector<double> &default_pose);
    bool hasCoordinate(const QString &name);
    void removeCoordinate(const QString &name);

    // 点云
    void addPointCloud(const std::vector<std::vector<double>> &points,
                       const QString &name = "default",
                       const QColor &color = Qt::green);
    void removePointCloud(const QString &name);
    bool hasPointCloud(const QString &name);
    void clearPointCloud();

    // 安全平面
    void setSafetyPlanesVisiable(bool visiable);
    void addSafetyPlane(
        const QString &name,
        const std::pair<std::vector<double>, std::int8_t> &pose);
    void removeSafetyPlane(const QString &name);
    void removeAllSafetyPlanes();
    void renameSafetyPlane(const QString &old_name, const QString &new_name);

    // 障碍物标记
    void setObstacleMarkersVisiable(bool visiable);
    void addObstacleMarker(const QString &name, const std::vector<double> &pose,
                           const std::vector<double> &size,
                           const QVector4D &color);
    void removeObstacleMarker(const QString &name);
    void removeAllObstacleMarkers();
    void renameObstacleMarker(const QString &old_name, const QString &new_name);

    // ----- 界面操作 -----
    /// 设置显示模式，控制各种元素的显隐
    void setShowOptions(uint8_t options);

    /// 将渲染界面 嵌入/移除(isEmbeded) 布局 gly
    void setRenderEmbeded(bool isEmbeded, QGridLayout *gly);

    /// 目标机器人是否存在
    /// 有些情况虽然目标机器人可以显示, 但没有目标位置信息
    void setHasTarget(bool visiable);

    /// TODO: 目标机器人显隐
    /// 移动界面设置目标值时, 即时没有目标机器人显隐图标, 也要显示目标机器人
    void setTargetVisiable(bool visiable);

    /// 设置主要显示窗口
    /// 如果不在其下, grab 无法截图
    /// TODO: 更名 setMainView, 待接口适配完再一起改
    void setMoveForm(QWidget *main_view);

    /// 能否旋转
    void setRotateEnable(bool rotate_enable);

    /// 根据模型大小设置默认视角尺寸
    void setDefaultSizeScale(int zoom_out_value, int down_move_value);

signals:
    void sigRefresh();

protected:
    void resizeGL(int w, int h) override;

private:
    void qssInit();
    void setupUi();

    void updateTargetVisiable();

private:
    Ui::RenderForm *ui;
    QWidget *main_view_{ nullptr };             ///< 主要显示窗口
    std::shared_ptr<Camera> camera_{ nullptr }; ///< 相机

    // 默认视角
    int default_zoom_out_{ 0 };
    int default_down_move_{ 0 };
    bool first_zoom_out_{ false };

    // 重力分量
    std::vector<double> gravity_component_{ std::vector<double>(3, 0.) };

    uint8_t show_options_; ///< 显示模式, 控制各元素显隐

    // 底座
    std::shared_ptr<BoxRenderer> r_base_{ nullptr };

    // 机器人
    std::shared_ptr<Q3dsRenderer> r_real_robot_{ nullptr }; ///< 真实机器人模型
    /// 真实机器人末端坐标系
    std::shared_ptr<AxisRenderer> r_real_robot_pose_{ nullptr };
    /// 目标机器人模型
    std::shared_ptr<Q3dsRenderer> r_target_robot_{ nullptr };
    bool has_target_{ true };
    bool target_visiable_{ false };

    std::shared_ptr<AxisRenderer> r_world_pose_{ nullptr }; ///< 世界坐标系

    // grab
    QCache<quint64, QPixmap> cache_pixmap_; ///< 机器人截图

    // 路点轨迹
    QMutex mtx_waypoints_; ///< waypoints_ 涉及线程安全
    QMap<void *, WaypointTrack> waypoints_;

    // 坐标轴
    QMap<QString, std::vector<double>> coordinates_;
    QMap<QString, std::shared_ptr<AxisRenderer>> r_coordinates_axis_;
    QMap<QString, std::shared_ptr<BoxRenderer>> r_coordinates_;
    bool coordinates_visiabled_{ false };

    // 点云
    QMap<QString, PointCloud> point_clouds_;

    // 安全平面
    bool safety_planes_visiabled_{ false };
    QMap<QString, std::pair<std::vector<double>, std::int8_t>> safety_planes_;
    QMap<QString, std::shared_ptr<BoxRenderer>> r_safety_planes_;
    QMap<QString, std::shared_ptr<AxisRenderer>> r_safety_planes_axis_;

    // 障碍物标记
    bool obstacle_markers_visiabled_{ false };
    QMap<QString, std::shared_ptr<BoxRenderer>> r_obstacle_markers_;
};

#endif // AUBORENDERVIEW_H
